---
title: "Input"
description: "Input is a component that allows users to enter text. It can be used to get user inputs in forms, search fields, and more."
---

import {inputContent} from "@/content/components/input";

# Input

Input is a component that allows users to enter text. It can be used to get user inputs in forms, search fields, and more.

<ComponentLinks component="input" reactAriaHook="useTextField" />

---

<CarbonAd/>

## Installation

<PackageManagers
  showGlobalInstallWarning
  commands={{
    cli: "npx heroui-cli@latest add input",
    npm: "npm install @heroui/input",
    yarn: "yarn add @heroui/input",
    pnpm: "pnpm add @heroui/input",
    bun: "bun add @heroui/input"
  }}
/>


## Import

<ImportTabs
  commands={{
    main: 'import {Input} from "@heroui/react";',
    individual: 'import {Input} from "@heroui/input";',
  }}
/>

## Usage

<CodeDemo title="Usage" files={inputContent.usage} />

### Disabled

<CodeDemo title="Disabled" files={inputContent.disabled} />

### Read Only

<CodeDemo title="Read Only" files={inputContent.readOnly} />

### Required

If you pass the `isRequired` property to the input, it will have a `danger` asterisk at
the end of the label and the input will be required.

<CodeDemo title="Required" files={inputContent.required} />

### Sizes

<CodeDemo title="Sizes" files={inputContent.sizes} />

### Colors

<CodeDemo title="Colors" files={inputContent.colors} />

### Variants

<CodeDemo title="Variants" files={inputContent.variants} />

### Radius

<CodeDemo title="Radius" files={inputContent.radius} />

### Label Placements

You can change the position of the label by setting the `labelPlacement` property to `inside`, `outside`, `outside-left` or `outside-top`.

<CodeDemo title="Label Placements" files={inputContent.labelPlacements} />

> **Note**: If the `label` is not passed, the `labelPlacement` property will be `outside` by default.

> **Note**: If the `labelPlacement` is `outside`, `label` is outside only when a placeholder is provided. 

> **Note**: If the `labelPlacement` is `outside-top` or `outside-left`, `label` is outside even if a placeholder is not provided.

### Password Input

You can use the `type` property to change the input type to `password`.

<CodeDemo title="Password Input" highlightedLines="25" files={inputContent.password} />

### Clear Button

If you pass the `isClearable` property to the input, it will have a clear button at the
end of the input, it will be visible when the input has a value.

<CodeDemo title="Clear Button" highlightedLines="7" files={inputContent.clearButton} />

### Start & End Content

You can use the `startContent` and `endContent` properties to add content to the start and end of the input.

<CodeDemo title="Start and End Content" files={inputContent.startEndContent} />

### With Description

You can add a description to the input by passing the `description` property.

<CodeDemo title="With Description" files={inputContent.description} />

### With Error Message

You can combine the `isInvalid` and `errorMessage` properties to show an invalid input. `errorMessage` is only shown when `isInvalid` is set to `true`.

<CodeDemo title="With Error Message" files={inputContent.errorMessage} />

Example with `regex` email validation:

<CodeDemo title="With Regex Validation" files={inputContent.regexValidation} />

### Controlled

You can use the `value` and `onValueChange` properties to control the input value.

<CodeDemo title="Controlled" files={inputContent.controlled} />

> **Note**: HeroUI `Input` also supports native events like `onChange`, useful for form libraries
> such as [Formik](https://formik.org/) and [React Hook Form](https://react-hook-form.com/).

### With Form

`Input` can be used with a `Form` component to leverage form state management. For more on form and validation behaviors, see the [Forms](/docs/guide/forms) guide.

#### Built-in Validation

`Input` supports the following [native HTML constraints](https://developer.mozilla.org/docs/Web/HTML/Constraint_validation):

- `isRequired` indicates that a field must have a value before the form can be submitted.
- `minLength` and `maxLength` specify the minimum and length of text input.
- `pattern` provides a custom regular expression that a text input must conform to.
- `type="email"` and `type="url"` provide built-in validation for email addresses and URLs.

When using native validation, error messages can be customized by passing a function to `errorMessage` and checking the [ValidityState](https://developer.mozilla.org/docs/Web/API/ValidityState) of `validationDetails`.

<CodeDemo title="Built-in Validation" files={inputContent.builtInValidation} />

#### Custom Validation

In addition to built-in constraints, you can provide a function to the `validate` property for custom validation.

<CodeDemo title="Custom Validation" files={inputContent.customValidation} />

#### Realtime Validation

If you want to display validation errors while the user is typing, you can control the field value and use the `isInvalid` prop along with the `errorMessage` prop.

<CodeDemo title="Realtime Validation" files={inputContent.realTimeValidation} />

#### Server Validation

Client-side validation provides immediate feedback, but you should also validate data on the server to ensure accuracy and security.
HeroUI allows you to display server-side validation errors by using the `validationErrors` prop in the `Form` component.
This prop should be an object where each key is the field `name` and the value is the error message.

<CodeDemo title="Server Validation" files={inputContent.serverValidation} />

## Slots

- **base**: Input wrapper, it handles alignment, placement, and general appearance.
- **label**: Label of the input, it is the one that is displayed above, inside or left of the input.
- **mainWrapper**: Wraps the `inputWrapper` when position is `outside` / `outside-left`.
- **inputWrapper**: Wraps the `label` (when it is inside) and the `innerWrapper`.
- **innerWrapper**: Wraps the `input`, the `startContent` and the `endContent`.
- **input**: The input element.
- **clearButton**: The clear button, it is at the end of the input.
- **helperWrapper**: Wraps the `description` and the `errorMessage`.
- **description**: The description of the input.
- **errorMessage**: The error message of the input.

### Custom Styles

You can customize the `Input` component by passing custom Tailwind CSS classes to the component slots.

<CodeDemo title="Custom Styles" highlightedLines="13-31" files={inputContent.customStyles} />

### Custom Implementation

In case you need to customize the input even further, you can use the `useInput` hook to create your own implementation.

<CodeDemo
  showPreview={false}
  showOpenInCodeSandbox={true}
  title="Custom Implementation"
  files={inputContent.customImpl}
/>

<Spacer y={4} />

## Data Attributes

`Input` has the following attributes on the `base` element:

- **data-invalid**:
  When the input is invalid. Based on `isInvalid` prop.
- **data-required**:
  When the input is required. Based on `isRequired` prop.
- **data-readonly**:
  When the input is readonly. Based on `isReadOnly` prop.
- **data-hover**:
  When the input is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-focus**:
  When the input is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-within**:
  When the input is being focused or any of its children. Based on [useFocusWithin](https://react-spectrum.adobe.com/react-aria/useFocusWithin.html).
- **data-focus-visible**:
  When the input is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-disabled**:
  When the input is disabled. Based on `isDisabled` prop.

<Spacer y={4} />

## Accessibility

- Built with a native `<input>` element.
- Visual and ARIA labeling support.
- Change, clipboard, composition, selection, and input event support.
- Required and invalid states exposed to assistive technology via ARIA.
- Support for description and error message help text linked to the input via ARIA.

<Spacer y={4} />

## API

### Input Props

<APITable
  data={[
    {
      attribute: "children",
      type: "ReactNode",
      description: "The content of the input.",
      default: "-"
    },
    {
      attribute: "variant",
      type: "flat | bordered | faded | underlined",
      description: "The variant of the input.",
      default: "flat"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "The color of the input.",
      default: "default"
    },
    {
      attribute: "size",
      type: "sm | md | lg",
      description: "The size of the input.",
      default: "md"
    },
    {
      attribute: "radius",
      type: "none | sm | md | lg | full",
      description: "The radius of the input.",
      default: "-"
    },
    {
      attribute: "label",
      type: "ReactNode",
      description: "The content to display as the label.",
      default: "-"
    },
    {
      attribute: "value",
      type: "string",
      description: "The current value of the input (controlled).",
      default: "-"
    },
    {
      attribute: "defaultValue",
      type: "string",
      description: "The default value of the input (uncontrolled).",
      default: "-"
    },
    {
      attribute: "placeholder",
      type: "string",
      description: "The placeholder of the input.",
      default: "-"
    },
    {
      attribute: "description",
      type: "ReactNode",
      description: "A description for the input. Provides a hint such as specific requirements for what to choose.",
      default: "-"
    },
    {
      attribute: "errorMessage",
      type: "ReactNode | ((v: ValidationResult) => ReactNode)",
      description: "An error message for the input. It is only shown when isInvalid is set to true",
      default: "-"
    },
    {
      attribute: "validate",
      type: "(value: string) => ValidationError | true | null | undefined",
      description: "Validate input values when committing (e.g. on blur), returning error messages for invalid values.",
      default: "-"
    },
    {
      attribute: "validationBehavior",
      type: "native | aria",
      description: "Whether to use native HTML form validation or ARIA validation. When wrapped in a Form component, the default is `aria`. Otherwise, the default is `native`.",
      default: "native"
    },
    {
      attribute: "minLength",
      type: "number",
      description: "The minimum length of the text input.",
      default: "-"
    },
    {
      attribute: "maxLength",
      type: "number",
      description: "The maximum length of the text input.",
      default: "-"
    },
    {
      attribute: "pattern",
      type: "string",
      description: "A regular expression that the input value is checked against.",
      default: "-"
    },
    {
      attribute: "type",
      type: "text | email | url | password | tel | search | file",
      description: "The type of the input.",
      default: "text"
    },
    {
      attribute: "startContent",
      type: "ReactNode",
      description: "Element to be rendered in the left side of the input.",
      default: "-"
    },
    {
      attribute: "endContent",
      type: "ReactNode",
      description: "Element to be rendered in the right side of the input.",
      default: "-"
    },
    {
      attribute: "labelPlacement",
      type: "inside | outside | outside-left",
      description: "The position of the label.",
      default: "inside"
    },
    {
      attribute: "fullWidth",
      type: "boolean",
      description: "Whether the input should take up the width of its parent.",
      default: "true"
    },
    {
      attribute: "isClearable",
      type: "boolean",
      description: "Whether the input should have a clear button.",
      default: "false"
    },
    {
      attribute: "isRequired",
      type: "boolean",
      description: "Whether user input is required on the input before form submission.",
      default: "false"
    },
    {
      attribute: "isReadOnly",
      type: "boolean",
      description: "Whether the input can be selected but not changed by the user.",
      default: "false"
    },
    {
      attribute: "isDisabled",
      type: "boolean",
      description: "Whether the input is disabled.",
      default: "false"
    },
    {
      attribute: "isInvalid",
      type: "boolean",
      description: "Whether the input is invalid.",
      default: "false"
    },
    {
      attribute: "baseRef",
      type: "RefObject<HTMLDivElement>",
      description: "The ref to the base element.",
      default: "-"
    },
    {
      attribute: "disableAnimation",
      type: "boolean",
      description: "Whether the input should be animated.",
      default: "false"
    },
    {
      attribute: "classNames",
      type: "Partial<Record<'base' | 'label' | 'inputWrapper' | 'innerWrapper' | 'mainWrapper' | 'input' | 'clearButton' | 'helperWrapper' | 'description' | 'errorMessage', string>>",
      description: "Allows to set custom class names for the Input slots.",
      default: "-"
    }
  ]}
/>

### Input Events

<APITable
  data={[
    {
      attribute: "onChange",
      type: "React.ChangeEvent<HTMLInputElement>",
      description: "Handler that is called when the element's value changes. You can pull out the new value by accessing event.target.value (string).",
      default: "-"
    },
    {
      attribute: "onValueChange",
      type: "(value: string) => void",
      description: "Handler that is called when the element's value changes.",
      default: "-"
    },
    {
      attribute: "onClear",
      type: "() => void",
      description: "Handler that is called when the clear button is clicked.",
      default: "-"
    }
  ]}
/>
